#include "../mqserver/mq_host.hpp"
#include <gtest/gtest.h>

class HostTest : public testing::Test
{
public:
    virtual void SetUp() override
    {
        std::unordered_map<std::string, std::string> empty_map = std::unordered_map<std::string, std::string>();
        _host = std::make_shared<mymq::VirtualHost>("host1", "./data/host1/message", "./data/host1/host1.db");

        // 声明交换机
        _host->declareExchange("exchange1", mymq::ExchangeType::DIRECT, true, false, empty_map);
        _host->declareExchange("exchange2", mymq::ExchangeType::DIRECT, true, false, empty_map);

        // 声明队列
        _host->declareQueue("queue1", true, false, false, empty_map);
        _host->declareQueue("queue2", true, false, false, empty_map);

        // 绑定
        _host->bind("exchange1", "queue1", "news.music.#");
        _host->bind("exchange1", "queue2", "news.music.#");
        _host->bind("exchange2", "queue1", "news.music.#");
        _host->bind("exchange2", "queue2", "news.music.#");

        // 发布消息
        _host->basicPublish("queue1", nullptr, "hello world 1");
        _host->basicPublish("queue1", nullptr, "hello world 2");
        _host->basicPublish("queue1", nullptr, "hello world 3");

        _host->basicPublish("queue2", nullptr, "hello world 1");
        _host->basicPublish("queue2", nullptr, "hello world 2");
        _host->basicPublish("queue2", nullptr, "hello world 3");

    }

    virtual void TearDown() override
    {
        _host->clear();
    }
public:
    mymq::VirtualHost::ptr _host;
};


TEST_F(HostTest, init_test)
{
    ASSERT_EQ(_host->existsExchange("exchange1"), true);
    ASSERT_EQ(_host->existsExchange("exchange2"), true);

    ASSERT_EQ(_host->existsQueue("queue1"), true);
    ASSERT_EQ(_host->existsQueue("queue2"), true);

    ASSERT_EQ(_host->existsBinding("exchange1", "queue1"), true);
    ASSERT_EQ(_host->existsBinding("exchange1", "queue2"), true);
    ASSERT_EQ(_host->existsBinding("exchange2", "queue1"), true);
    ASSERT_EQ(_host->existsBinding("exchange2", "queue2"), true);

    mymq::MessagePtr msg1 = _host->basicConsume("queue1");
    ASSERT_EQ(msg1->payload().body(), std::string("hello world 1"));
    mymq::MessagePtr msg2 = _host->basicConsume("queue1");
    ASSERT_EQ(msg2->payload().body(), std::string("hello world 2"));
    mymq::MessagePtr msg3 = _host->basicConsume("queue1");
    ASSERT_EQ(msg3->payload().body(), std::string("hello world 3"));

    mymq::MessagePtr msg4 = _host->basicConsume("queue1");
    ASSERT_EQ(msg4.get(), nullptr);
}

TEST_F(HostTest, removeExchange_test)
{
    _host->deleteExchange("exchange1");
    ASSERT_EQ(_host->existsExchange("exchange1"), false);
    ASSERT_EQ(_host->existsBinding("exchange1", "queue1"), false);
    ASSERT_EQ(_host->existsBinding("exchange1", "queue2"), false);
}

TEST_F(HostTest, removeQueue_test)
{
    _host->deleteQueue("queue1");
    ASSERT_EQ(_host->existsQueue("queue1"), false);
    ASSERT_EQ(_host->existsBinding("exchange1", "queue1"), false);
    ASSERT_EQ(_host->existsBinding("exchange2", "queue1"), false);

    mymq::MessagePtr msg1 = _host->basicConsume("queue1");
    ASSERT_EQ(msg1.get(), nullptr);
}

TEST_F(HostTest, ack_test)
{
    mymq::MessagePtr msg1 = _host->basicConsume("queue1");
    ASSERT_EQ(msg1->payload().body(), std::string("hello world 1"));
    _host->basicAck(std::string("queue1"), msg1->payload().properties().id());

    mymq::MessagePtr msg2 = _host->basicConsume("queue1");
    ASSERT_EQ(msg2->payload().body(), std::string("hello world 2"));
    _host->basicAck(std::string("queue1"), msg2->payload().properties().id());

    mymq::MessagePtr msg3 = _host->basicConsume("queue1");
    ASSERT_EQ(msg3->payload().body(), std::string("hello world 3"));
    _host->basicAck(std::string("queue1"), msg3->payload().properties().id());
}


int main()
{
    testing::InitGoogleTest();
    RUN_ALL_TESTS();
    return 0;
}